﻿using DAL;
using IService;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Service
{
    public class NumberingRuleService : INumberingRuleService
    {
        private readonly AppDbContext _context;
        private readonly ILogger<NumberingRuleService> _logger;

        public NumberingRuleService(AppDbContext context, ILogger<NumberingRuleService> logger)
        {
            _context = context;
            _logger = logger;
        }

        /// <summary>
        /// 检查是否需要按天重置（第二天重置为001）
        /// </summary>
        private bool ShouldResetByDate(NumberingRule rule)
        {
            return rule.LastUpdateTime.Date < DateTime.Today;
        }

        /// <summary>
        /// 检查是否需要增加位数（超过最大值时）
        /// </summary>
        private bool ShouldIncreaseDigit(NumberingRule rule, int nextSerial)
        {
            int maxThreshold = GetMaxSerialThreshold(rule);
            return nextSerial > maxThreshold;
        }

        /// <summary>
        /// 计算下一个流水号（核心逻辑）
        /// </summary>
        private (int nextSerial, bool digitIncreased) CalculateNextSerialNumber(NumberingRule rule)
        {
            bool digitIncreased = false;
            int nextSerial;

            // 1. 检查是否跨天（到了第二天），是则重置为1
            if (ShouldResetByDate(rule))
            {
                _logger.LogInformation("检测到跨天（第二天），重置流水号为1。RuleId: {RuleId}, 最后更新日期: {LastDate}, 当前日期: {Today}",
                    rule.RuleId, rule.LastUpdateTime.Date, DateTime.Today);
                nextSerial = 1; // 第二天首次生成时重置为1
            }
            else
            {
                // 2. 当天内：基于当前最大值 + 步长递增
                nextSerial = rule.MaxValue + rule.Step;
            }

            // 3. 检查是否需要增加位数（如999→1000时，3位→4位）
            if (ShouldIncreaseDigit(rule, nextSerial))
            {
                int currentDigit = int.Parse(rule.SerialNumberDigit);
                rule.SerialNumberDigit = (currentDigit + 1).ToString();
                digitIncreased = true;
                _logger.LogInformation("流水号位数增加，RuleId: {RuleId}, 新位数: {NewDigit}", rule.RuleId, rule.SerialNumberDigit);
            }

            return (nextSerial, digitIncreased);
        }

        /// <summary>
        /// 生成完整编号
        /// </summary>
        private string GenerateFullNumber(NumberingRule rule, int serialNumber)
        {
            string datePart = DateTime.Now.ToString("yyyyMMdd");
            string formattedSerial = serialNumber.ToString($"D{rule.SerialNumberDigit}");
            return $"{rule.NumberPrefix}{datePart}{formattedSerial}";
        }

        /// <summary>
        /// 生成编号并更新最大值（录单成功后调用）- 核心：仅按ID
        /// </summary>
        public async Task<string> GenerateAndUpdateNumberAsync(long ruleId)
        {
            using var transaction = await _context.Database.BeginTransactionAsync();
            try
            {
                // 行锁确保并发安全
                var rule = await _context.NumberingRule
                    .FromSqlRaw("SELECT * FROM sys_number_rule WITH (ROWLOCK, UPDLOCK) WHERE rule_id = {0}", ruleId)
                    .Where(r => r.IsDelete == "0")
                    .FirstOrDefaultAsync();

                if (rule == null)
                    throw new InvalidOperationException($"未找到ID为【{ruleId}】的有效编号规则");

                // 计算流水号 + 生成编号
                var (nextSerial, digitIncreased) = CalculateNextSerialNumber(rule);
                string fullNumber = GenerateFullNumber(rule, nextSerial);

                // 更新数据库最大值及相关字段
                rule.MaxValue = nextSerial;
                rule.LastUpdateTime = DateTime.Now;
                rule.UpdateTime = DateTime.Now;
                rule.UpdateBy = "system";

                int affectedRows = await _context.SaveChangesAsync();
                if (affectedRows > 0)
                {
                    await transaction.CommitAsync();
                    _logger.LogInformation("生成编号成功，RuleId: {RuleId}, 编号: {Number}, 新MaxValue: {MaxValue}",
                        ruleId, fullNumber, nextSerial);
                    return fullNumber;
                }
                else
                {
                    await transaction.RollbackAsync();
                    throw new InvalidOperationException("更新数据库失败，未影响任何行");
                }
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();
                _logger.LogError(ex, "生成编号失败，RuleId: {RuleId}", ruleId);
                throw;
            }
        }

        /// <summary>
        /// 录单成功后更新最大值（仅按ID）
        /// </summary>
        public async Task UpdateMaxValueAfterSuccessAsync(long ruleId, int currentSerial)
        {
            using var transaction = await _context.Database.BeginTransactionAsync();
            try
            {
                var rule = await _context.NumberingRule
                    .FromSqlRaw("SELECT * FROM sys_number_rule WITH (ROWLOCK, UPDLOCK) WHERE rule_id = {0}", ruleId)
                    .Where(r => r.IsDelete == "0")
                    .FirstOrDefaultAsync();

                if (rule == null)
                    throw new InvalidOperationException($"未找到ID为【{ruleId}】的有效编号规则");

                // 校验：传入流水号必须大于当前最大值
                if (currentSerial <= rule.MaxValue)
                {
                    _logger.LogWarning("流水号无效，不更新。RuleId: {RuleId}, 当前MaxValue: {MaxValue}, 传入Serial: {CurrentSerial}",
                        ruleId, rule.MaxValue, currentSerial);
                    await transaction.RollbackAsync();
                    return;
                }

                // 检查位数是否需要增加
                bool digitIncreased = false;
                if (ShouldIncreaseDigit(rule, currentSerial))
                {
                    int currentDigit = int.Parse(rule.SerialNumberDigit);
                    rule.SerialNumberDigit = (currentDigit + 1).ToString();
                    digitIncreased = true;
                }

                // 更新最大值
                rule.MaxValue = currentSerial;
                rule.LastUpdateTime = DateTime.Now;
                rule.UpdateTime = DateTime.Now;
                rule.UpdateBy = "system";

                int affectedRows = await _context.SaveChangesAsync();
                if (affectedRows > 0)
                {
                    await transaction.CommitAsync();
                    _logger.LogInformation("更新最大值成功，RuleId: {RuleId}, 新MaxValue: {MaxValue}", ruleId, currentSerial);
                }
                else
                {
                    await transaction.RollbackAsync();
                    throw new InvalidOperationException("更新最大值失败");
                }
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync();
                _logger.LogError(ex, "更新最大值失败，RuleId: {RuleId}", ruleId);
                throw;
            }
        }

        /// <summary>
        /// 生成预览编号（不更新数据库，仅按ID）
        /// </summary>
        public async Task<string> GenerateNumberByRuleIdAsync(long ruleId)
        {
            var rule = await GetNumberingRuleByIdAsync(ruleId);
            if (rule == null)
                throw new InvalidOperationException($"未找到ID为【{ruleId}】的有效编号规则");

            var (nextSerial, digitIncreased) = CalculateNextSerialNumber(rule);
            string fullNumber = GenerateFullNumber(rule, nextSerial);

            _logger.LogInformation("生成预览编号，RuleId: {RuleId}, 预览编号: {Number}", ruleId, fullNumber);
            return fullNumber;
        }

        #region 基础查询实现（移除TargetForm相关）
        public async Task<List<NumberingRule>> GetAllNumberingRulesAsync()
        {
            return await _context.NumberingRule
                .Where(r => r.IsDelete == "0")
                .ToListAsync();
        }

        public async Task<NumberingRule> GetNumberingRuleByIdAsync(long id)
        {
            return await _context.NumberingRule
                .FirstOrDefaultAsync(r => r.RuleId == id && r.IsDelete == "0");
        }

        // 移除：按目标表单查询实现（不再使用）
        // public async Task<NumberingRule> GetNumberingRuleByTargetFormAsync(string targetForm)
        // {
        //     return await _context.NumberingRule
        //         .FirstOrDefaultAsync(r => r.TargetForm == targetForm && r.IsDelete == "0");
        // }

        public async Task<List<NumberingRule>> GetNumberingRulesByIdsAsync(List<long> ids)
        {
            if (ids == null || !ids.Any())
                return new List<NumberingRule>();

            return await _context.NumberingRule
                .Where(r => ids.Contains(r.RuleId) && r.IsDelete == "0")
                .AsNoTracking()
                .ToListAsync();
        }
        #endregion

        #region 数据操作实现（移除TargetForm校验）
        private async Task AddRuleToDbAsync(NumberingRule rule)
        {
            await _context.NumberingRule.AddAsync(rule);
            await _context.SaveChangesAsync();
        }

        private async Task UpdateRuleInDbAsync(NumberingRule rule)
        {
            var existingRule = await _context.NumberingRule.FindAsync(rule.RuleId);
            if (existingRule == null)
                throw new KeyNotFoundException($"未找到ID为 {rule.RuleId} 的编号规则");

            // 仅更新需要修改的字段，移除TargetForm
            existingRule.NumberPrefix = rule.NumberPrefix;
            existingRule.SerialNumberDigit = rule.SerialNumberDigit;
            existingRule.Step = rule.Step;
            existingRule.NumberGenerationRule = rule.NumberGenerationRule;
            existingRule.MaxValue = rule.MaxValue;
            existingRule.LastUpdateTime = rule.LastUpdateTime;
            existingRule.IsDelete = rule.IsDelete;
            existingRule.UpdateTime = rule.UpdateTime;
            existingRule.UpdateBy = rule.UpdateBy;

            await _context.SaveChangesAsync();
        }

        private async Task BatchUpdateRulesInDbAsync(List<NumberingRule> rules)
        {
            if (rules == null || !rules.Any())
                return;

            foreach (var rule in rules)
            {
                var existingRule = await _context.NumberingRule.FindAsync(rule.RuleId);
                if (existingRule != null)
                {
                    _context.Entry(existingRule).CurrentValues.SetValues(rule);
                }
            }
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 新增规则（移除TargetForm重复校验）
        /// </summary>
        public async Task AddNumberingRuleAsync(NumberingRule rule)
        {
            ValidateNumberingRule(rule);

            // 移除：TargetForm重复校验
            // var existingRule = await GetNumberingRuleByTargetFormAsync(rule.TargetForm);
            // if (existingRule != null)
            //     throw new InvalidOperationException($"目标表单 '{rule.TargetForm}' 已存在编号规则");

            // 初始化默认值（TargetForm设为null）
            rule.MaxValue = 0;
            rule.LastUpdateTime = DateTime.Now;
            rule.CreateTime = DateTime.Now;
            rule.UpdateTime = DateTime.Now;
            rule.IsDelete = "0";
            rule.TargetForm = null; // 强制清空目标表单
            rule.CreateBy = string.IsNullOrEmpty(rule.CreateBy) ? "admin" : rule.CreateBy;
            rule.UpdateBy = string.IsNullOrEmpty(rule.UpdateBy) ? "admin" : rule.UpdateBy;

            await AddRuleToDbAsync(rule);
        }

        /// <summary>
        /// 更新规则（移除TargetForm相关校验）
        /// </summary>
        public async Task UpdateNumberingRuleAsync(NumberingRule rule)
        {
            ValidateNumberingRule(rule);

            var existingRule = await GetNumberingRuleByIdAsync(rule.RuleId);
            if (existingRule == null)
                throw new InvalidOperationException($"未找到ID为 {rule.RuleId} 的编号规则");

            // 移除：TargetForm变更校验
            // if (existingRule.TargetForm != rule.TargetForm)
            // {
            //     var conflictRule = await GetNumberingRuleByTargetFormAsync(rule.TargetForm);
            //     if (conflictRule != null && conflictRule.RuleId != rule.RuleId)
            //         throw new InvalidOperationException($"目标表单 '{rule.TargetForm}' 已存在其他编号规则");
            // }

            // 更新字段（移除TargetForm）
            existingRule.NumberPrefix = rule.NumberPrefix;
            existingRule.SerialNumberDigit = rule.SerialNumberDigit;
            existingRule.Step = rule.Step;
            existingRule.NumberGenerationRule = rule.NumberGenerationRule;
            existingRule.UpdateBy = rule.UpdateBy ?? "admin";
            existingRule.UpdateTime = DateTime.Now;

            await UpdateRuleInDbAsync(existingRule);
        }
        #endregion

        #region 条件查询与重置（修改查询参数）
        /// <summary>
        /// 条件查询（支持按RuleId筛选，移除TargetForm）
        /// </summary>
        public async Task<List<NumberingRule>> QueryNumberingRulesAsync(
            long? ruleId, string prefix, DateTime? startTime, DateTime? endTime, string timeRule)
        {
            var query = _context.NumberingRule.Where(r => r.IsDelete == "0");

            // 新增：按RuleId筛选
            if (ruleId.HasValue && ruleId > 0)
                query = query.Where(r => r.RuleId == ruleId.Value);

            // 按前缀筛选
            if (!string.IsNullOrEmpty(prefix))
                query = query.Where(r => r.NumberPrefix.Contains(prefix));

            // 按时间规则筛选
            if (!string.IsNullOrEmpty(timeRule) && timeRule != "请选择")
                query = query.Where(r => r.TimeRule.Contains(timeRule));

            // 按更新时间范围筛选
            if (startTime.HasValue)
                query = query.Where(r => r.LastUpdateTime >= startTime.Value);
            if (endTime.HasValue)
                query = query.Where(r => r.LastUpdateTime <= endTime.Value);

            return await query.ToListAsync();
        }

        /// <summary>
        /// 重置所有过期规则
        /// </summary>
        public async Task ResetAllExpiredRulesAsync()
        {
            var today = DateTime.Today;
            var expiredRules = await _context.NumberingRule
                .Where(r => r.IsDelete == "0" && r.LastUpdateTime.Date < today)
                .ToListAsync();

            if (!expiredRules.Any())
                return;

            foreach (var rule in expiredRules)
            {
                rule.MaxValue = 0;
                rule.LastUpdateTime = DateTime.Now;
                rule.UpdateTime = DateTime.Now;
                rule.UpdateBy = "system";
            }

            await BatchUpdateRulesInDbAsync(expiredRules);
        }

        /// <summary>
        /// 重置单个规则（按ID）
        /// </summary>
        public async Task ResetNumberingRuleAsync(long ruleId)
        {
            var rule = await GetNumberingRuleByIdAsync(ruleId);
            if (rule == null)
                throw new KeyNotFoundException($"未找到ID为 {ruleId} 的编号规则");

            rule.MaxValue = 0;
            rule.LastUpdateTime = DateTime.Now;
            rule.UpdateTime = DateTime.Now;
            rule.UpdateBy = "system";
            await UpdateRuleInDbAsync(rule);
        }
        #endregion

        #region 辅助方法（修改校验逻辑）
        /// <summary>
        /// 计算流水号最大阈值
        /// </summary>
        private int GetMaxSerialThreshold(NumberingRule rule)
        {
            if (!int.TryParse(rule.SerialNumberDigit, out int digitCount) || digitCount <= 0)
                throw new InvalidOperationException($"规则ID：{rule.RuleId} 的流水号位数无效（{rule.SerialNumberDigit}）");
            return (int)Math.Pow(10, digitCount) - 1;
        }

        public async Task<bool> NumberingRuleExistsAsync(long id)
        {
            return await _context.NumberingRule
                .AnyAsync(r => r.RuleId == id && r.IsDelete == "0");
        }

        public async Task DeleteNumberingRuleAsync(long id)
        {
            var rule = await _context.NumberingRule.FindAsync(id);
            if (rule == null)
                throw new KeyNotFoundException($"编号规则 ID {id} 不存在");

            _context.NumberingRule.Remove(rule);
            await _context.SaveChangesAsync();
        }

        /// <summary>
        /// 校验规则（移除TargetForm非空校验）
        /// </summary>
        private void ValidateNumberingRule(NumberingRule rule)
        {
            if (rule == null)
                throw new ArgumentNullException(nameof(rule), "编号规则不能为空");
            // 移除：TargetForm非空校验
            // if (string.IsNullOrWhiteSpace(rule.TargetForm))
            //     throw new ArgumentException("目标表单不能为空");
            if (string.IsNullOrWhiteSpace(rule.NumberPrefix))
                throw new ArgumentException("编号前缀不能为空");
            if (string.IsNullOrWhiteSpace(rule.SerialNumberDigit)
                || !int.TryParse(rule.SerialNumberDigit, out int digit)
                || digit <= 0)
                throw new ArgumentException("流水号位数必须是大于0的数字（如3、5）");
            if (rule.Step <= 0)
                throw new ArgumentException("步长必须大于0");
        }

        private string GenerateNumberRuleString(NumberingRule model)
        {
            var ruleBuilder = new StringBuilder();
            ruleBuilder.Append(model.NumberPrefix ?? "");
            ruleBuilder.Append("YYYYMMDD");

            if (!int.TryParse(model.SerialNumberDigit, out int digit))
                throw new InvalidOperationException($"流水号位数格式错误：'{model.SerialNumberDigit}'，必须是数字");
            ruleBuilder.Append(new string('0', digit));

            return ruleBuilder.ToString();
        }
        #endregion

    }
}